/*
 * Copyright (C) 2014 Realtek Semiconductor Corp. 
 * All Rights Reserved.
 *
 * This program is the proprietary software of Realtek Semiconductor
 * Corporation and/or its licensors, and only be used, duplicated, 
 * modified or distributed under the authorized license from Realtek. 
 *
 * ANY USE OF THE SOFTWARE OTHER THAN AS AUTHORIZED UNDER 
 * THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. 
 *
 * Purpose : Definition of OMCI generic OS general APIs
 *
 * Feature : The file includes the following modules and sub-modules
 *           (1) OMCI generic OS general APIs
 */

#include "gos_linux.h"
#include "gos_general.h"
#include "gos_type.h"

int gWordBase;
BOOL gBigEndian;


void GOS_Get_Word_Base(void)
{
    void *testPrt = NULL;
    gWordBase = sizeof(testPrt);

}

void GOS_Get_Endian(void)
{
    unsigned int x = 1;

    if ((((char *)&x)[0]) == 1)
    {
        //printf("little endian\n");
        gBigEndian = FALSE;
    }
    else
    {
        gBigEndian = TRUE;
    }

}

UINT16 GOS_Htons(UINT16 a)
{
    if (!gBigEndian)
    {
        UINT16 low, high;
        low = (a & 0xFF00) >> 8;
        high = a & 0x00FF;

        return (high << 8) | low;
    }
    else
    {
        return a;
    }
}


UINT16 GOS_Ntohs(UINT16 b)
{
    return GOS_Htons(b);
}


UINT32 GOS_Htonl(UINT32 a)
{
    if (!gBigEndian)
    {
        UINT32 byte1, byte2, byte3, byte4;
        byte1 = (a & 0xFF000000) >> 24;
        byte2 = (a & 0x00FF0000) >> 16;
        byte3 = (a & 0x0000FF00) >> 8;
        byte4 = (a & 0x000000FF) >> 0;

        return (byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1;
    }
    else
    {
        return a;
    }
}


UINT32 GOS_Ntohl(UINT32 b)
{
    return GOS_Htonl(b);
}


UINT64 GOS_Ntohll(UINT64 c)
{
	if (!gBigEndian)
	{
		UINT64 byte1, byte2, byte3, byte4, byte5, byte6, byte7, byte8;
		byte1 = (c & 0xFF00000000000000ULL) >> 56;
		byte2 = (c & 0x00FF000000000000ULL) >> 48;
		byte3 = (c & 0x0000FF0000000000ULL) >> 40;
		byte4 = (c & 0x000000FF00000000ULL) >> 32;
		byte5 = (c & 0x00000000FF000000ULL) >> 24;
		byte6 = (c & 0x0000000000FF0000ULL) >> 16;
		byte7 = (c & 0x000000000000FF00ULL) >> 8;
		byte8 = (c & 0x00000000000000FFULL) >> 0;

		return (byte8 << 56) | (byte7 << 48) | (byte6 << 40) | (byte5 << 32) | (byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1;
	}	
	else
	{
		return c;
	}
}


UINT64 GOS_Htonll(UINT64 c)
{
    return GOS_Ntohll(c);
}

#if 0
UINT64 GOS_BuffToUINT64(CHAR *pBuf, UINT32 bufSize)
{
    UINT64 val;
    UINT8 temp[8], i;
//    UINT32* pLow = (UINT32*)&(temp[4]);
//    UINT32* pHigh = (UINT32*)temp;

    GOS_ASSERT(bufSize > 0 && bufSize <= sizeof(UINT64));
    memset(temp, 0x00, 8);
    
    for (i = 1; i <= bufSize; i++)
    {
        temp[8 - i] = (UINT8)pBuf[bufSize - i];
    }

    return val;
}
#endif

void GOS_UINT64ToBuff(UINT64 value, CHAR* pBuf,  UINT32 bufSize)
{
    memcpy(pBuf, (CHAR *)&value + sizeof(UINT64) - bufSize, bufSize);
}


UINT16 GOS_GetUINT16(UINT16* pVal)
{
    GOS_ASSERT(pVal);

    if(0x1 & (CASTING(pVal)))
    {
        UINT16 val;
        memcpy(&val, pVal, sizeof(UINT16));
        return val;
    }

    return *pVal;
}


void GOS_SetUINT16(UINT16* pDest, UINT16 src)
{
    GOS_ASSERT(pDest);

    if (0x1 & (CASTING(pDest)))
    {
        memcpy(pDest, &src, sizeof(UINT16));
    }
    else
    {
        *pDest = src;
    }
}


UINT32 GOS_GetUINT32(UINT32* pVal)
{
    GOS_ASSERT(pVal);

    if (0x3 & (CASTING(pVal)))
    {
        UINT32 val;
        memcpy(&val, pVal, sizeof(UINT32));
        return val;
    }

    return *pVal;
}

    
void GOS_SetUINT32(UINT32* pDest, UINT32 src)
{
    GOS_ASSERT(pDest);

    if (0x3 & (CASTING(pDest)))
    {
        memcpy(pDest, &src, sizeof(UINT32));
    }
    else
    {
        // The address is 4-byte aligned here
        *pDest = src;
    }
}

UINT64 GOS_GetUINT64(UINT64* pVal)
{
    GOS_ASSERT(pVal);

    if (0x7 & (CASTING(pVal)))
    {
        UINT64 val;
        memcpy(&val, pVal, sizeof(UINT64));
        return val;
    }

    return *pVal;
}


void GOS_SetU64(UINT64* pDest, UINT64 src)
{
    GOS_ASSERT(pDest);

    if (0x7 & (CASTING(pDest)))
    {
        memcpy(pDest, &src, sizeof(UINT64));
    }
    else
    {
        // The address is 8-byte aligned here
        *pDest = src;
    }
}

UINT8 *GOS_HtonByte(UINT8 *pData, UINT32 len)
{
	if (!gBigEndian)
	{

		UINT8 *ptr = (UINT8 *)malloc(sizeof(UINT8) * len);
		UINT32 i;
		if (ptr)
		{
			for(i = 0; i < len; i++)
				ptr[len -i -1] = pData[i];
			memcpy(pData, ptr, len);
			free(ptr);
			return pData;
		}
		return NULL;
	}
	else
	{
		return pData;
	}
}


